Android VSync 核心机制深入解读

1/6/2025

本文基于 aosp android-14.0.0_r15 源码进行分析。

学习 Vsync 原理的几个要点:

  • 了解 Vsync 是什么以及 Android Vsync 的基本框架
  • SurfaceFlinger 如何接收和处理硬件 Vsync 信号
  • Vsync 信号的申请与分发,包含了 App 与 SF
  • 如何使用 Perfetto 查看 Vsync 信号

# 1. VSync 是什么?

如果你玩过 PC 上的大型游戏,应该知道游戏中通常有一个叫做垂直同步的选项,如果不开这个选项,游戏过程中可能有画面撕裂的情况。

画面撕裂 VS 画面不撕裂

图片来自 https://sspai.com/post/63440

左侧是画面撕裂的情况,右侧是正常情况。

这种情况出现的主要原因是屏幕的刷新和主机的渲染不同步,假如,你是富哥,买了一张 4090 显卡,主机渲染图形非常快,但是你的显示器还是创业初期闲鱼捡的垃圾,刷新很慢(60hz),你游戏的时候,没有开垂直同步,当一帧还没全部刷新到屏幕上,下一帧数据又来了,显示器通常会中断当前帧的刷新,去刷新下一帧,这个时候,显示器上显示的就是当前帧和上一帧组合的图像,如果显示内容变化较大,你就能察觉到画面的撕裂。

这个问题最初是在 PC 上被重视和解决的,GPU 厂商开发出了一种防止屏幕被撕裂的技术方案,全称 Vertical Synchronization(中文名垂直同步,简称 VSync)。基本思路就是显示器在屏幕刷新之前向外提供一个信号,主机端根据此信号选择合适的策略完成画面的刷新,避免数据刷新和屏幕扫描不匹配(撕裂)的情况发生。

# 2. Android VSync 基本框架

从硬件视角来看 VSync 其实就是一个电平信号,显示器的驱动板上有一个单独的引脚,这个引脚会根据显示器的刷新率定时的改变其高低电平。主机端需要有一个单独的 GPIO 与之相连,获取其信号变化;软件视角中的 VSync 其实就是一个 GPIO 的中断。

当 Vsync 信号到来时,linux 内核就会收到一个中断,内核会根据对应的中断号去调用对应的中断处理函数。VSync 的中断处理函数会调用到 DRM 模块中,DRM 模块进一步又会调用到 HWComposor Hal 模块。

SurfaceFligner 在初始化时会向 HWComposor HAL 注册一个 Binder 回调(实际就是 sf 这边的一个匿名 Binder),HWComposor HAL 收到硬件 Vsync 信号后就会调用到这个回调,从何将硬件 Vsync 信号发送给 SurfaceFlinger。

SurfaceFlinger 中的回调函数收到硬件传递来的 Vsync 信号后,会使用 VsyncSchedule 将 Vsync 信号到达时间和 Vsync 信号周期等信息记录下来。当数据到达 6 个以上时,会通过简单线性回归公式。当 App 需要绘制图像时,Choreographer 通过 binder 向 VsyncSchedule 发起一个请求信号,VsyncSchedule 收到请求后会通过刚才记录的信息计算出软件 Vsync 信号,然后通过 socket 将该信号传递给 App,App 收到信号后开始绘制渲染工作。

20240709224423

# 3. SurfaceFlinger 如何接收到硬件 Vsync 信号

上一节中我们说到,SurfaceFlinger 在初始化时会向 HWComposor HAL 注册一个 Binder 回调。HWComposor HAL 收到硬件 Vsync 信号后就会调用到这个回调,从何将硬件 Vsync 信号发送给 SurfaceFlinger。

接下来我们就来分析回调的注册过程。在 SurfaceFlinger 的初始化过程中,会构建一个 HWComposor 对象,该对象时用于与 HardWare Composor HAL 服务进行 Binder 通信的辅助类。接着会向 HardWare Composor HAL 注册一个 HWC2::ComposerCallback 回调对象,这里传入的时 SurfaceFlinger 自己,SurfaceFlinger 实现了该接口。

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    // .....
    
    // 关注点1
    // 构建 HWComposor 对象
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    // 关注点2
    // 注册回调,回调接口 HWC2::ComposerCallback,SurfaceFlinger 实现了该接口
    // 当硬件 Vsync 信号到来时,会调用该回调
    mCompositionEngine->getHwComposer().setCallback(*this);
    // ......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

主要有两个要点需要关注:

  • 关注点1,构建 HWComposer 对象
  • 关注点2,向 HardWare Composor HAL 注册一个 HWC2::ComposerCallback 回调对象

# 3.1 HWComposer 的初始化

相关的类图如下,我们可以参考类图来阅读本小节代码。

20250106222127

HWComposer 是与 Hardware Composor HAL 服务通信的辅助类,这里通过工厂模式构建一个 HWComposer 对象,接下来我们通过其构造的过程来了解其组成与功能。

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    // .....
    
    // 关注点1
    // 构建 HWComposor 对象,并赋值给 mCompositionEngine 内部 mHwComposer 成员
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    // ......
}
1
2
3
4
5
6
7
8
9
10

getFactory 返回的是 DefaultFactory,DefaultFactory 内部的 createHWComposer 实现如下:

// /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp

std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
    return std::make_unique<android::impl::HWComposer>(serviceName);
}
1
2
3
4
5

这里就是简单的直接 new 一个 android::impl::HWComposer,对应的构造函数实现如下:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

HWComposer::HWComposer(const std::string& composerServiceName)
        // create 构建一个 android::Hwc2::AidlComposer
      : HWComposer(Hwc2::Composer::create(composerServiceName)) {} 


// 接着调用另一个重载
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
        // 新构建的 android::Hwc2::AidlComposer 会赋值给 HWComposer 对象的成员 mComposer  
      : mComposer(std::move(composer)),        
        mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
        mUpdateDeviceProductInfoOnHotplugReconnect(
                sysprop::update_device_product_info_on_hotplug_reconnect(false)) {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这里会构建一个 android::Hwc2::AidlComposer 对象,并赋值给 HWComposer 对象的成员 mComposer。

std::unique_ptr<Composer> Composer::create(const std::string& serviceName) {
    if (AidlComposer::isDeclared(serviceName)) { // 新版本都会走该分支,使用 aidl hal
        return std::make_unique<AidlComposer>(serviceName);
    }

    return std::make_unique<HidlComposer>(serviceName);
}
1
2
3
4
5
6
7

这里 new 一个 AidlComposer 对象返回。

接着看 android::Hwc2::AidlComposer 的初始化过程:

// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
    std::shared_ptr<AidlIComposer> mAidlComposer;
    std::shared_ptr<AidlIComposerClient> mAidlComposerClient;

// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
AidlComposer::AidlComposer(const std::string& serviceName) {
    // This only waits if the service is actually declared

    // 通过 ServiceManager 获取到 HWComposer Hal 的代理端对象 mAidlComposer
    mAidlComposer = AidlIComposer::fromBinder(
            ndk::SpAIBinder(AServiceManager_waitForService(instance(serviceName).c_str()))); // 获取 Binder 服务
    if (!mAidlComposer) {
        LOG_ALWAYS_FATAL("Failed to get AIDL composer service");
        return;
    }

    // 拿到匿名 Binder 服务的代理端对象 mAidlComposerClient
    if (!mAidlComposer->createClient(&mAidlComposerClient).isOk()) { // 获取匿名 Binder 服务
        LOG_ALWAYS_FATAL("Can't create AidlComposerClient, fallback to HIDL");
        return;
    }

    addReader(translate<Display>(kSingleReaderKey));

    // If unable to read interface version, then become backwards compatible.
    int32_t version = 1;
    const auto status = mAidlComposerClient->getInterfaceVersion(&version);
    if (!status.isOk()) {
        ALOGE("getInterfaceVersion for AidlComposer constructor failed %s",
              status.getDescription().c_str());
    }
    mSupportsBufferSlotsToClear = version > 1;
    if (!mSupportsBufferSlotsToClear) {
        if (sysprop::clear_slots_with_set_layer_buffer(false)) {
            mClearSlotBuffer = sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBX_8888,
                                                       GraphicBuffer::USAGE_HW_COMPOSER |
                                                               GraphicBuffer::USAGE_SW_READ_OFTEN |
                                                               GraphicBuffer::USAGE_SW_WRITE_OFTEN,
                                                       "AidlComposer");
            if (!mClearSlotBuffer || mClearSlotBuffer->initCheck() != ::android::OK) {
                LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
                return;
            }
        }
    }

    ALOGI("Loaded AIDL composer3 HAL service");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

在 AidlComposer 构造函数中,首先通过 ServiceManager 获取到 HWComposer Hal 的代理端对象 mAidlComposer,接着通过 mAidlComposer 发起远程调用获取到匿名 Binder 服务的代理端对象 mAidlComposerClient。两个都是与 HWComposer Hal 通信的代理端。Android 中很多这种情况,有了一个代理端,还需要另一个匿名 Binder 的代理端。总而言之,AidlComposer 类包装了与 HWC Hal 交互的接口,让使用方更为方便地与 HWC Hal 通信。

# 3.2 HWC2::ComposerCallback 回调对象的注册

HwComposer 初始化完成以后,接下来会给 HwComposer 注册一个回调对象:

 // 这里的 this 就是 SurfaceFlinger 对象本身,因为它实现了 HWC2::ComposerCallback 回调接口
    mCompositionEngine->getHwComposer().setCallback(*this);
1
2

给 HwComposor 对象注册了回调对象 this,也就是 SurfaceFlinger 对象,SurfaceFlinger 继承了 HWC2::ComposerCallback 接口。

HWC2::ComposerCallback 接口中定义了 VSYNC信号、插拔显示器等的回调事件函数:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
    // 显示器热插拔事件
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
    // 显示器 refresh 刷新事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
    // VSYNC 信号事件
    virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
                                    std::optional<hal::VsyncPeriodNanos>) = 0;
    //......
};
1
2
3
4
5
6
7
8
9
10
11

HWC2::ComposerCallback 最终会被封装为一个 Bn 服务端对象,作为一个匿名 Binder 服务端发送给 Hardware Composer Hal。当 Hardware Composer Hal 收到硬件 Vsync 信号时,通过这个匿名 Binder 回调到 SurfaceFlinger 中。具体的代码实现如下:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

void HWComposer::setCallback(HWC2::ComposerCallback& callback) {
    loadCapabilities();
    loadLayerMetadataSupport();
    loadOverlayProperties();
    loadHdrConversionCapabilities();

    if (mRegisteredCallback) {
        ALOGW("Callback already registered. Ignored extra registration attempt.");
        return;
    }
    mRegisteredCallback = true;

    mComposer->registerCallback(callback);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

接着调用成员 mComposer 的 registerCallback 函数,mComposer 的实际类型是 AidlComposer。

// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
void AidlComposer::registerCallback(HWC2::ComposerCallback& callback) {
    if (mAidlComposerCallback) {
        ALOGE("Callback already registered");
    }

    // 包装成 AidlIComposerCallbackWrapper,这是一个 Bn 对象,匿名 Binder 服务,作为回调。
    mAidlComposerCallback = ndk::SharedRefBase::make<AidlIComposerCallbackWrapper>(callback);
    AIBinder_setMinSchedulerPolicy(mAidlComposerCallback->asBinder().get(), SCHED_FIFO, 2);

    // 通过匿名 Binder 发起远程调用,注册回调。
    const auto status = mAidlComposerClient->registerCallback(mAidlComposerCallback);
    if (!status.isOk()) {
        ALOGE("registerCallback failed %s", status.getDescription().c_str());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

首先把 HWC2::ComposerCallback 包装成一个 AidlComposerCallback 对象:

class AidlIComposerCallbackWrapper : public BnComposerCallback {
   
    // ......

}
1
2
3
4
5

可以看出这是一个 Bn 对象,是一个匿名 Binder 服务,作为回调注册给 HardWare Composer HAL。

20241014153557

当 HardWare Composer HAL 中接收到硬件 Vsync 信号后,就会通过这里 Binder 回调,将信号发送给 SurfaceFlinger。

# 4. SurfaceFlinger 如何处理硬件 Vsync 信号

上一节说到,SF 向 HWC 注册了一个 HWC2::ComposerCallback 回调:

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
    // 显示器热插拔事件
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
    // 显示器 refresh 刷新事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
    // VSYNC 信号事件
    virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
                                    std::optional<hal::VsyncPeriodNanos>) = 0;
    //......
};
1
2
3
4
5
6
7
8
9
10
11

HWC2::ComposerCallback 接口的实现是 SurfaceFlinger 类。当硬件 Vsync 信号发生时,经过层层调用,最终会调用到 SurfaceFlinger::onComposerHalVsync 函数。

# 4.1 相关对象的初始化

SurfaceFlinger 在初始化时,初始化了一些对象,这些对象是在硬件 Vsync 信号发生时,具体就是 SurfaceFlinger::onComposerHalVsync 被调用时,完成以下的功能:

  • 记录硬件 Vsync 信号的周期,到达时间
  • 计算一个 Vsync 信号次序与 Vsync 信号到达时间的一元一次关系,后续可以用这个关系模拟出软件 Vsync 信号

接下来我们就来看相关对象的初始化:

    std::unique_ptr<scheduler::Scheduler> mScheduler;
    scheduler::ConnectionHandle mAppConnectionHandle;
    scheduler::ConnectionHandle mSfConnectionHandle;

    std::unique_ptr<scheduler::VsyncConfiguration> mVsyncConfiguration;    

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

// 参数就是前面构建的 DisplayDevice 对象
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    using namespace scheduler;


    // 从前面构建的 RefreshRateSelector 获取 RefreshRate
    // activeMode 就是当前屏幕的刷新率
    const auto activeMode = display->refreshRateSelector().getActiveMode();
    const Fps activeRefreshRate = activeMode.fps;

    // new 一个 RefreshRateStats
    mRefreshRateStats =
            std::make_unique<RefreshRateStats>(*mTimeStats, activeRefreshRate, hal::PowerMode::OFF);

    // 构建一个 VsyncConfiguration 对象,内部主要保存了 Vsync 的周期与频率
    mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
    
    // 关注点1
    // 构建一个 VsyncModulator 对象
    // 根据事务调度和刷新率的变化调整 Vsync。
    auto modulatorPtr = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());

    // 关注点2
    // this + 前面构造的对象,初始化 Scheduler 对象
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast< &>(*this), features,
                                             std::move(modulatorPtr));

    // 关注点3
    mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
std::unique_ptr<scheduler::VsyncConfiguration> DefaultFactory::createVsyncConfiguration(
        Fps currentRefreshRate) {
    
    // pixel6 上这个属性是 true
    if (property_get_bool("debug.sf.use_phase_offsets_as_durations", false)) {
        return std::make_unique<scheduler::impl::WorkDuration>(currentRefreshRate);
    } else {
        return std::make_unique<scheduler::impl::PhaseOffsets>(currentRefreshRate);
    }
}
1
2
3
4
5
6
7
8
9
10
WorkDuration::WorkDuration(Fps currentRefreshRate)
      : WorkDuration(currentRefreshRate, getProperty("debug.sf.late.sf.duration").value_or(-1),
                     getProperty("debug.sf.late.app.duration").value_or(-1),
                     getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
                     getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
                     getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration),
                     getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration),
                     getProperty("debug.sf.hwc.min.duration").value_or(0)) {
    validateSysprops();
}
                                                                                                                                                                                
WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
                           nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
                           nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
                           nsecs_t hwcMinWorkDuration)
      : VsyncConfiguration(currentRefreshRate),
        mSfDuration(sfDuration),
        mAppDuration(appDuration),
        mSfEarlyDuration(sfEarlyDuration),
        mAppEarlyDuration(appEarlyDuration),
        mSfEarlyGpuDuration(sfEarlyGpuDuration),
        mAppEarlyGpuDuration(appEarlyGpuDuration),
        mHwcMinWorkDuration(hwcMinWorkDuration) {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

WorkDuration 中有 4 组参数:

  • app phase 和 SF phase 就是正常情况下使用的。
  • early app phase 和 early SF phase 是在切换屏幕帧率的时候使用的。
  • GL early app phase 和 GL early SF phase 是在 SF 使用 GPU 合成的时候使用的。
  • mHwcMinWorkDurationHWC 的最小合成时间

父类 VsyncConfiguration 的构造函数:

Fps mRefreshRateFps GUARDED_BY(mLock);

VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {}
1
2
3

接着看后续:

    VsyncConfigSet getCurrentConfigs() const override EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return getConfigsForRefreshRateLocked(mRefreshRateFps);
    }
1
2
3
4
    mutable ftl::SmallMap<Fps, VsyncConfigSet, 2, FpsApproxEqual> mOffsetsCache GUARDED_BY(mLock);  
    
    VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRateLocked(Fps fps) const {
        if (const auto offsets = mOffsetsCache.get(fps)) {
            return offsets->get();
        }

        // 一开始没有成员,这里会构造一个
        const auto [it, _] = mOffsetsCache.try_emplace(fps, constructOffsets(fps.getPeriodNsecs()));
        return it->second;
    } 
1
2
3
4
5
6
7
8
9
10
11
VsyncConfigSet WorkDuration::constructOffsets(nsecs_t vsyncDuration) const {
    const auto sfDurationFixup = [vsyncDuration](nsecs_t duration) {
        return duration == -1 ? std::chrono::nanoseconds(vsyncDuration) - 1ms
                              : std::chrono::nanoseconds(duration);
    };

    const auto appDurationFixup = [vsyncDuration](nsecs_t duration) {
        return duration == -1 ? std::chrono::nanoseconds(vsyncDuration)
                              : std::chrono::nanoseconds(duration);
    };

    const auto sfEarlyDuration = sfDurationFixup(mSfEarlyDuration);
    const auto appEarlyDuration = appDurationFixup(mAppEarlyDuration);
    const auto sfEarlyGpuDuration = sfDurationFixup(mSfEarlyGpuDuration);
    const auto appEarlyGpuDuration = appDurationFixup(mAppEarlyGpuDuration);
    const auto sfDuration = sfDurationFixup(mSfDuration);
    const auto appDuration = appDurationFixup(mAppDuration);

    return {
            .early =
                    {

                            .sfOffset = sfEarlyDuration.count() < vsyncDuration
                                    ? sfDurationToOffset(sfEarlyDuration, vsyncDuration)
                                    : sfDurationToOffset(sfEarlyDuration, vsyncDuration) -
                                            vsyncDuration,

                            .appOffset = appDurationToOffset(appEarlyDuration, sfEarlyDuration,
                                                             vsyncDuration),

                            .sfWorkDuration = sfEarlyDuration,
                            .appWorkDuration = appEarlyDuration,
                    },
            .earlyGpu =
                    {

                            .sfOffset = sfEarlyGpuDuration.count() < vsyncDuration

                                    ? sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration)
                                    : sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration) -
                                            vsyncDuration,

                            .appOffset = appDurationToOffset(appEarlyGpuDuration,
                                                             sfEarlyGpuDuration, vsyncDuration),
                            .sfWorkDuration = sfEarlyGpuDuration,
                            .appWorkDuration = appEarlyGpuDuration,
                    },
            .late =
                    {

                            .sfOffset = sfDuration.count() < vsyncDuration

                                    ? sfDurationToOffset(sfDuration, vsyncDuration)
                                    : sfDurationToOffset(sfDuration, vsyncDuration) - vsyncDuration,

                            .appOffset =
                                    appDurationToOffset(appDuration, sfDuration, vsyncDuration),

                            .sfWorkDuration = sfDuration,
                            .appWorkDuration = appDuration,
                    },
            .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
    };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
VsyncModulator::VsyncModulator(const VsyncConfigSet& config, Now now)
      : mVsyncConfigSet(config),
        mNow(now),
        mTraceDetailedInfo(base::GetBoolProperty("debug.sf.vsync_trace_detailed_info", false)) {}
1
2
3
4

接着看 Scheduler 对象的初始化。

Scheduler 是生成和派发软件 VSync 的整体调度器,继承自 MessageQueue。构造函数实现如下:

// compositor 和 callback 都是传的 SurfaceFlinger 对象 
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
                     sp<VsyncModulator> modulatorPtr)
      :impl::MessageQueue(compositor),
        mFeatures(features),
        mVsyncModulator(std::move(modulatorPtr)),
        mSchedulerCallback(callback) {} 

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
MessageQueue::MessageQueue(ICompositor& compositor)
      : MessageQueue(compositor, sp<Handler>::make(*this)) {}

MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
      : mCompositor(compositor),
        mLooper(sp<Looper>::make(kAllowNonCallbacks)),  // SurfaceFlinger 主线程
        mHandler(std::move(handler)) {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Scheduler 的构造函数对内部的几个成员做了初始化:

  • mCompositor,传入的是 Surfaceflinger 对象
  • mFeatures,前面获取的一些 flags
  • mVsyncModulator,根据事务调度和刷新率的变化调整 Vsync
  • mSchedulerCallback,传入的是 Surfaceflinger 对象
  • mLooper mHandler:事件循环相关类

这些类的关系如下图所示:

20240710121944

Scheduler::registerDisplay 实现如下:

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    registerDisplayInternal(displayId, std::move(selectorPtr),
                            // new 一个 VsyncSchedule 对象,重要
                            std::make_shared<VsyncSchedule>(displayId, mFeatures));
}
1
2
3
4
5
6

先 new 一个 VsyncSchedule 对象,再调用 registerDisplayInternal 函数。

先看 new VsyncSchedule 的过程:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features)
      : mId(id),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}
1
2
3
4
5
6
7
8
9

在构造函数中初始化了以下几个重要成员:

  • mTracker
  • mDispatch
  • mController

我们一个个看,mTracker 通过 createTracker 初始化:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
    // TODO(b/144707443): Tune constants.
    constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
    constexpr size_t kHistorySize = 20;
    constexpr size_t kMinSamplesForPrediction = 6;
    constexpr uint32_t kDiscardOutlierPercent = 20;

    return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
                                            kMinSamplesForPrediction, kDiscardOutlierPercent);
}
1
2
3
4
5
6
7
8
9
10
11

就是 new 一个 VSyncPredictor 对象,VSyncPredictor 在 VsyncSchedule 的语境中为一个 Tracker,是负责综合各方因素根据算法由硬件 VSync 计算出软件 VSync 周期的工具类。

VSyncPredictor 的构造函数实现如下:

    // /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
    std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);
    std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
      : mId(id),
        mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
        kHistorySize(historySize),
        kMinimumSamplesForPrediction(minimumSamplesForPrediction),
        kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
        mIdealPeriod(idealPeriod) {
    resetModel();
}

void VSyncPredictor::resetModel() {
    std::lock_guard lock(mMutex);
    mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
    clearTimestamps();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

构造函数中,初始化了很多参数值。这些参数都是用于后续计算软件 VSync 的。接着调用 resetModel(),给 mRateMap 插入一组初始化数据,mRateMap 是一个 unordered_map 类型的数据,用于保存硬件 Vsync 相关的数据。

mDispatch 成员通过 createDispatch 初始化:

VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
    using namespace std::chrono_literals;

    // TODO(b/144707443): Tune constants.
    constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
    constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;

    return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), std::move(tracker),
                                                     kGroupDispatchWithin.count(),
                                                     kSnapToSameVsyncWithin.count());
}
1
2
3
4
5
6
7
8
9
10
11

mDispatch 的实际类型是 VsyncDispatch,createDispatch 函数中会 new 一个 VSyncDispatchTimerQueue 对象(VsyncDispatch 的子类)并返回,该对象在 VsyncSchedule 的语境中为一个 Dispather,负责将 VSync 分发到使用者。

CallbackMap mCallbacks GUARDED_BY(mMutex);

VSyncDispatchTimerQueue::VSyncDispatchTimerQueue(std::unique_ptr<TimeKeeper> tk,
                                                 VsyncSchedule::TrackerPtr tracker,
                                                 nsecs_t timerSlack, nsecs_t minVsyncDistance)
      : mTimeKeeper(std::move(tk)),
        mTracker(std::move(tracker)),
        mTimerSlack(timerSlack),
        mMinVsyncDistance(minVsyncDistance) {}
1
2
3
4
5
6
7
8
9

mController 成员通过 createController 函数初始化:

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId id,
                                                             VsyncTracker& tracker,
                                                             FeatureFlags features) {
    // TODO(b/144707443): Tune constants.
    constexpr size_t kMaxPendingFences = 20;
    const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);

    auto reactor = std::make_unique<VSyncReactor>(id, std::make_unique<SystemClock>(), tracker,
                                                  kMaxPendingFences, hasKernelIdleTimer);

    reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
    return reactor;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
VSyncReactor::VSyncReactor(PhysicalDisplayId id, std::unique_ptr<Clock> clock,
                           VSyncTracker& tracker, size_t pendingFenceLimit,
                           bool supportKernelIdleTimer)
      : mId(id),
        mClock(std::move(clock)),
        mTracker(tracker),
        mPendingLimit(pendingFenceLimit),
        mSupportKernelIdleTimer(supportKernelIdleTimer) {}
1
2
3
4
5
6
7
8

mController 的实际类型是 VsyncController。在 createController 函数中会 new 一个 VSyncReactor 对象(VsyncController 的子类)并返回。这个对象的主要作用是负责传递 HWVsync,presentFence 信号

到这里,VsyncSchedule 就初始化完成了,相关类的关系如下图所示:

20240730215531

接着看 registerDisplayInternal 的实现:

display::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays

void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
                                        RefreshRateSelectorPtr selectorPtr,
                                        VsyncSchedulePtr schedulePtr) {
    demotePacesetterDisplay();

    std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
    {
        std::scoped_lock lock(mDisplayLock);
        // 用 RefreshRateSelectorPtr VsyncSchedule 对象构建一个 Display 对象
        mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
        
        // 应该就是刚才初始化的 VsyncSchedule 对象
        pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
    }
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

把 display RefreshRateSelectorPtr VsyncSchedule 三个对象插入 mDisplays 成员中关联起来,实际后两个参数会构建一个 Display 对象再插入

接着调用 applyNewVsyncSchedule 函数:

void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {

    onNewVsyncSchedule(vsyncSchedule->getDispatch());

    // mConnections 还是 empty 的,后续代码实际都不会执行
    std::vector<android::EventThread*> threads;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        threads.reserve(mConnections.size());
        for (auto& [_, connection] : mConnections) {
            threads.push_back(connection.thread.get());
        }
    }
    for (auto* thread : threads) {
        thread->onNewVsyncSchedule(vsyncSchedule);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

这里会接着调用 onNewVsyncSchedule 函数:

void MessageQueue::onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // The old registration needs to be deleted after releasing mVsync.mutex to
    // avoid deadlock. This is because the callback may be running on the timer
    // thread. In that case, timerCallback sets
    // VSyncDispatchTimerQueueEntry::mRunning to true, then attempts to lock
    // mVsync.mutex. But if it's already locked, the VSyncCallbackRegistration's
    // destructor has to wait until VSyncDispatchTimerQueueEntry::mRunning is
    // set back to false, but it won't be until mVsync.mutex is released.
    oldRegistration.reset();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

接着调用 onNewVsyncScheduleLocked 函数:

    struct Vsync {
        frametimeline::TokenManager* tokenManager = nullptr;

        mutable std::mutex mutex;
        std::unique_ptr<scheduler::VSyncCallbackRegistration> registration GUARDED_BY(mutex);
        TracedOrdinal<std::chrono::nanoseconds> workDuration
                GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
        TimePoint lastCallbackTime GUARDED_BY(mutex);
        std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex);
        TracedOrdinal<int> value = {"VSYNC-sf", 0};
    };


Vsync mVsync;

std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) {

    // 这个时候 mVsync.registration 为空,reschedule 是 false
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    // 关键点
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback , this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    // 不进入
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

这里核心点就是 new 一个 VSyncCallbackRegistration 对象并保存在 mVsync 的 registration 成员中。

std::optional<VSyncDispatch::CallbackToken> mToken;
std::shared_ptr<VSyncDispatch> mDispatch;

VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
                                                     VSyncDispatch::Callback callback,
                                                     std::string callbackName)
      : mDispatch(std::move(dispatch)),
        mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
1
2
3
4
5
6
7
8

VSyncCallbackRegistration 的构造函数中,会将 callback 注册到 mDispatch,这里的 callback 就是 MessageQueue::vsyncCallback。

using CallbackToken = StrongTyping<size_t, class CallbackTokenTag, Compare, Hash>;

using CallbackMap =
            std::unordered_map<CallbackToken, std::shared_ptr<VSyncDispatchTimerQueueEntry>>;

CallbackMap mCallbacks GUARDED_BY(mMutex);

size_t mCallbackToken GUARDED_BY(mMutex) = 0;

// callback 参数是 MessageQueue::vsyncCallback
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback callback, std::string callbackName) {
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,
                             std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
                                                                            std::move(callback),
                                                                            mMinVsyncDistance))
                    .first->first};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这里把回调函数包装为 VSyncDispatchTimerQueueEntry 对象,并插入 mCallbacks 中。


using Callback =
            std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime)>;

const VSyncDispatch::Callback mCallback;

VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string name,
                                                           VSyncDispatch::Callback callback,
                                                           nsecs_t minVsyncDistance)
      : mName(std::move(name)),
        mCallback(std::move(callback)),
        mMinVsyncDistance(minVsyncDistance) {}
1
2
3
4
5
6
7
8
9
10
11
12

后续会通过 VSyncCallbackRegistration 去申请 Vsync 信号,申请过程中会调用到这个回调函数来分发软件 Vsync 信号,这个我们会在本节后续章节详细分析。

到这里,我们 Scheduler 相关的类图就增加了两个类:

20240710181631

# 4.2 硬件 Vsync 信号的处理

// /android-14.0.0_r15/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                        std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
    ATRACE_NAME(vsyncPeriod
                        ? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str()
                        : ftl::Concat(__func__, ' ', hwcDisplayId).c_str());

    Mutex::Autolock lock(mStateLock);
    // 关注点1
    if (const auto displayIdOpt = getHwComposer().onVsync(hwcDisplayId, timestamp)) {
        // 关注点 2
        if (mScheduler->addResyncSample(*displayIdOpt, timestamp, vsyncPeriod)) {
            // 关注点 3 Vsync 的周期变化了,会执行 modulateVsync 函数,配置一些参数
            // period flushed
            mScheduler->modulateVsync(displayIdOpt, &VsyncModulator::onRefreshRateChangeCompleted);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

传入的三个参数:

  • hwcDisplayId 表示显示器的 ID,意思是当前的 Vysnc 信号来自哪个显示器
  • 参数 timestamp 表示 Vsync 信号的时间点
  • vsyncPeriod 表示连续两个 Vsync 信号的时间间隔

三个关注点:

  • 关注点 1:HwComposer::onVsync,对 ID 做转换,如果返回非 0 值,表示有当前 Vsync 信号有对应的屏幕,需要处理。
  • 关注点 2:Scheduler::addResyncSample,添加硬件 Vsync 信号记录,信号记录超过 6 个则使用简单线性回归公式计算计算软件 Vsync 信号的模型
  • 关注点3,Scheduler::addResyncSample 函数如果返回 true,表示 Vsync 的周期变了,需要调用 Scheduler::modulateVsync 重新配置相关参数

# 4.2.1 HwComposer::onVsync,确认硬件 Vsync 是否需要处理

// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp

// ID 类型转换外加一些特殊情况判断
std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
                                                     nsecs_t timestamp) {

    // 转换 id
    const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
    if (!displayIdOpt) {
        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
        return {};
    }

    RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});

    auto& displayData = mDisplayData[*displayIdOpt];

    {
        // There have been reports of HWCs that signal several vsync events
        // with the same timestamp when turning the display off and on. This
        // is a bug in the HWC implementation, but filter the extra events
        // out here so they don't cause havoc downstream.
        if (timestamp == displayData.lastPresentTimestamp) {
            ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
                  to_string(*displayIdOpt).c_str(), timestamp);
            return {};
        }

        // 记录一下数据
        displayData.lastPresentTimestamp = timestamp;
    }

    ATRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
               displayData.vsyncTraceToggle);
    displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;

    // 确保信号有对应的屏幕
    return displayIdOpt;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

对 ID 做转换,如果返回非 0 值,表示有当前 Vsync 信号有对应的屏幕,需要处理。

# 4.2.2 Scheduler::addResyncSample,记录硬件 Vsync 数据,计算用于估算软件 Vsync 信号的一元一次方程

bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
                                std::optional<nsecs_t> hwcVsyncPeriodIn) {
    
    // 输入的数据转换一下格式
    const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
        return Period::fromNs(nanos);
    });

    // 拿到 VsyncSchedule 对象
    auto schedule = getVsyncSchedule(id);
    if (!schedule) {
        ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
        return false;
    }

    //返回之表示 Vsync 周期是否改变
    return schedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
                                     hwcVsyncPeriod);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

getVsyncSchedule 的实现如下:

auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
        -> ConstVsyncSchedulePtr {
    std::scoped_lock lock(mDisplayLock);
    return getVsyncScheduleLocked(idOpt);
}

auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
        -> ConstVsyncSchedulePtr {
    ftl::FakeGuard guard(kMainThreadContext);

    if (!idOpt) {
        LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
        idOpt = mPacesetterDisplayId;
    }

    const auto displayOpt = mDisplays.get(*idOpt);
    if (!displayOpt) {
        return nullptr;
    }
    return displayOpt->get().schedulePtr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

可以看出 getVsyncSchedule 就是从成员变量 mDisplays 中拿到 VsyncSchedule 对象。

接着调用 VsyncSchedule:addResyncSample 函数,


// ControllerPtr 是 VsyncController 指针
const ControllerPtr mController;

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
                                    ftl::Optional<Period> hwcVsyncPeriod) {
    bool needsHwVsync = false;
    bool periodFlushed = false;
    {
        std::lock_guard<std::mutex> lock(mHwVsyncLock);
        if (mHwVsyncState == HwVsyncState::Enabled) {
            needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(),
                                                            hwcVsyncPeriod.transform(&Period::ns),
                                                            &periodFlushed);
        }
    }
    if (needsHwVsync) {
        enableHardwareVsync(callback);
    } else {
        disableHardwareVsync(callback, false /* disallow */);
    }
    return periodFlushed;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

接着调用 mController->addHwVsyncTimestamp。mController 的实际类型是 VsyncController 指针,VsyncController 内部均为纯虚函数,是一个接口类,具体的实现类是 VSyncReactor。

VsyncReactor 扮演了 controller 的角色,一方面,记录收到的硬件 Vsync 信号,记录的数据主要包含了硬件 Vsync 到达的时间点和 Vsync 信号的周期。另一方面,当记录的数据足够多时,使用简单线性回归公式计算出一个一元一次方程(主要是斜率和偏移),x 为 Vsync 的次序,y 为 Vsync 的到达的时间。当后续 App 需要绘制时或者sf 需要合成时,就可以利用这个一元一次方程模拟软件 Vsync 信号。

为什么需要使用软件模拟,不直接使用硬件 Vsync 信号?

主要是 App 的渲染和 Sf 的合成需要一个合适的相位差,这样图形的绘制与合成效率才能更高,这是单个硬件 Vsync 信号做不到的。

接下来,我们就来看看 VSyncReactor::addHwVsyncTimestamp 的具体实现:

    /*
     * Adds a hw sync timestamp to the model. The controller will use the timestamp
     * time as a vsync signal.
     *
     * \param [in] timestamp       The HW Vsync timestamp
     * \param [in] hwcVsyncPeriod  The Vsync period reported by composer, if available
     * \param [out] periodFlushed  True if the vsync period changed is completed
     * \return                     True if the model needs more vsync signals to make
     *                             an accurate prediction,
     *                             False otherwise
     */

bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                       bool* periodFlushed) {
    assert(periodFlushed);

    std::lock_guard lock(mMutex);
    if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
        ATRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value);
        if (mPeriodTransitioningTo) {
            mTracker.setPeriod(*mPeriodTransitioningTo);
            *periodFlushed = true;
        }

        if (mLastHwVsync) {
            mTracker.addVsyncTimestamp(*mLastHwVsync);
        }
        mTracker.addVsyncTimestamp(timestamp);

        endPeriodTransition();
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    } else if (mPeriodConfirmationInProgress) {
        ATRACE_FORMAT("VSR %" PRIu64 ": still confirming period", mId.value);
        mLastHwVsync = timestamp;
        mMoreSamplesNeeded = true;
        *periodFlushed = false;
    } else {
        ATRACE_FORMAT("VSR %" PRIu64 ": adding sample", mId.value);
        *periodFlushed = false;
        mTracker.addVsyncTimestamp(timestamp);
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    }

    if (!mMoreSamplesNeeded) {
        setIgnorePresentFencesInternal(false);
    }
    return mMoreSamplesNeeded;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

里面有很多逻辑判断,一方面要根据已有的数据判断硬件 Vsync 周期是否变化,结果保存在参数 periodFlushed 中,另一方面就是要记录硬件 Vsync 的数据,数据量足够时还需要计算出一个一元一次方程,用于后续的 Vsync 信号软件模拟。

  • mTracker::setPeriod 添加周期数据
  • mTracker::addVsyncTimestamp 添加信号到达时间

mTracker 的实际类型是 VSyncPredictor,主要作用是记录和计算硬件 Vsync 数据。

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
    
    struct Model {
        nsecs_t slope; // 斜率
        nsecs_t intercept; // 截距
    };

    std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);

    nsecs_t mIdealPeriod GUARDED_BY(mMutex);

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.cpp

void VSyncPredictor::setPeriod(nsecs_t period) {
    ATRACE_FORMAT("%s %s", __func__, to_string(mId).c_str());
    traceInt64("VSP-setPeriod", period);

    std::lock_guard lock(mMutex);
    static constexpr size_t kSizeLimit = 30;
    if (CC_UNLIKELY(mRateMap.size() == kSizeLimit)) {
        mRateMap.erase(mRateMap.begin());
    }

    mIdealPeriod = period;
    if (mRateMap.find(period) == mRateMap.end()) {
        mRateMap[mIdealPeriod] = {period, 0};
    }

    clearTimestamps();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

mIdealPeriod 记录 Vsync 的周期,mRateMap 记录了周期与斜率截距的 map 关系,斜率截距还没有计算,这里初始化为 0.


// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
// 用于保存硬件 Vsync 信号到达的时间
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
// 用于记录,周期与斜率截距的 map 关系
std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
    std::lock_guard lock(mMutex);

    // ......
    
    if (mTimestamps.size() != kHistorySize) {
        mTimestamps.push_back(timestamp); // 记录数据
        mLastTimestampIndex = next(mLastTimestampIndex);
    } else {
        mLastTimestampIndex = next(mLastTimestampIndex);
        mTimestamps[mLastTimestampIndex] = timestamp;
    }

    traceInt64If("VSP-ts", timestamp);

    // kMinimumSamplesForPrediction 的值为 6
    // 少于 6 个数据,直接返回
    // mIdealPeriod 是 16.6,也就是 60hz 
    const size_t numSamples = mTimestamps.size();
    if (numSamples < kMinimumSamplesForPrediction) {
        mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
        return true;
    }

    // 有六个数据后,使用简单线性回归公式计算出斜率和截距
    // X 是 Vsync 信号的次序
    // Y 是 Vsync 信号的到达时间
    // 注释中有简单线性回归的公式

    // This is a 'simple linear regression' calculation of Y over X, with Y being the
    // vsync timestamps, and X being the ordinal of vsync count.
    // The calculated slope is the vsync period.
    // Formula for reference:
    // Sigma_i: means sum over all timestamps.
    // mean(variable): statistical mean of variable.
    // X: snapped ordinal of the timestamp
    // Y: vsync timestamp
    //
    //         Sigma_i( (X_i - mean(X)) * (Y_i - mean(Y) )
    // slope = -------------------------------------------
    //         Sigma_i ( X_i - mean(X) ) ^ 2
    //
    // intercept = mean(Y) - slope * mean(X)
    //

    std::vector<nsecs_t> vsyncTS(numSamples); //搜集 Vsync 信号时间 y轴
    std::vector<nsecs_t> ordinals(numSamples); // 搜集 Vsycn 信号顺序 x轴

    // Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
    const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
    auto it = mRateMap.find(mIdealPeriod);
    auto const currentPeriod = it->second.slope; 

    // The mean of the ordinals must be precise for the intercept calculation, so scale them up for
    // fixed-point arithmetic.
    constexpr int64_t kScalingFactor = 1000;  // 顺序值相比时间值太小了,做发大处理,发大的倍数就是 1000

    nsecs_t meanTS = 0; // Vsync 信号时间平均值
    nsecs_t meanOrdinal = 0; // Vsync 信号顺序平均值

    for (size_t i = 0; i < numSamples; i++) {
        // 时间使用相对值
        const auto timestamp = mTimestamps[i] - oldestTS;
        vsyncTS[i] = timestamp;
        meanTS += timestamp;

        // 计算顺序的方法
        const auto ordinal = currentPeriod == 0
                ? 0
                : (vsyncTS[i] + currentPeriod / 2) / currentPeriod * kScalingFactor;
        ordinals[i] = ordinal;
        meanOrdinal += ordinal;
    }

    // 计算出平均值
    meanTS /= numSamples;  
    meanOrdinal /= numSamples;


    for (size_t i = 0; i < numSamples; i++) {
        vsyncTS[i] -= meanTS;
        ordinals[i] -= meanOrdinal;
    }

    nsecs_t top = 0;
    nsecs_t bottom = 0;
    for (size_t i = 0; i < numSamples; i++) {
        top += vsyncTS[i] * ordinals[i]; 
        bottom += ordinals[i] * ordinals[i];
    }

    if (CC_UNLIKELY(bottom == 0)) { // 特殊情况处理
        it->second = {mIdealPeriod, 0};
        clearTimestamps();
        return false;
    }

    nsecs_t const anticipatedPeriod = top * kScalingFactor / bottom;  //截距
    nsecs_t const intercept = meanTS - (anticipatedPeriod * meanOrdinal / kScalingFactor); // 斜率

    auto const percent = std::abs(anticipatedPeriod - mIdealPeriod) * kMaxPercent / mIdealPeriod;
    if (percent >= kOutlierTolerancePercent) {
        it->second = {mIdealPeriod, 0};
        clearTimestamps();
        return false;
    }

    // perfetto 中应该可以看到这两个值
    traceInt64If("VSP-period", anticipatedPeriod);
    traceInt64If("VSP-intercept", intercept);

    // 计算出的结果保存在 mRateMap 中
    // anticipatedPeriod 就是 斜率
    // intercept 就是截距
    // 后续就可以根据这两个数据模拟出软件 VSync
    it->second = {anticipatedPeriod, intercept}; // 数据记录到 mRateMap 中

    ALOGV("model update ts %" PRIu64 ": %" PRId64 " slope: %" PRId64 " intercept: %" PRId64,
          mId.value, timestamp, anticipatedPeriod, intercept);
    return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

# 4.2.3 硬件 Vsync 周期变化后的处理

回到 SurfaceFlinger::onComposerHalVsync 函数中:

// /android-14.0.0_r15/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                        std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
    ATRACE_NAME(vsyncPeriod
                        ? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str()
                        : ftl::Concat(__func__, ' ', hwcDisplayId).c_str());

    Mutex::Autolock lock(mStateLock);
    // 关注点1
    if (const auto displayIdOpt = getHwComposer().onVsync(hwcDisplayId, timestamp)) {
        // 关注点 2
        if (mScheduler->addResyncSample(*displayIdOpt, timestamp, vsyncPeriod)) {
            // 关注点 3 Vsync 的周期变化了,会执行 modulateVsync 函数,配置一些参数
            // period flushed
            mScheduler->modulateVsync(displayIdOpt, &VsyncModulator::onRefreshRateChangeCompleted);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

addResyncSample 如果返回 false,表示硬件 Vsync 信号的周期没有变化。addResyncSample 如果返回 true,表示硬件 Vsync 信号的周期改变了,接着就会调用 Scheduler::modulateVsync 来修改硬件 Vsync 周期相关的变量。

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h

    template <typename... Args,
              typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
    void modulateVsync(std::optional<PhysicalDisplayId> id, Handler handler, Args... args) {
        if (id) {
            std::scoped_lock lock(mDisplayLock);
            ftl::FakeGuard guard(kMainThreadContext);
            if (id != mPacesetterDisplayId) {
                return;
            }
        }
        // handler 回调获取到 config
        if (const auto config = (*mVsyncModulator.*handler)(args...)) {
            setVsyncConfig(*config, getPacesetterVsyncPeriod());
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

通过 handler 参数获取到 config, congfig 是 Vsync 相关的配置。handler 实际类型是 VsyncModulator::onRefreshRateChangeCompleted:

using VsyncConfigOpt = std::optional<VsyncConfig>;

// /frameworks/native/services/surfaceflinger/Scheduler/VsyncModulator.cpp
VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeCompleted() {
    if (!mRefreshRateChangePending) return std::nullopt;
    mRefreshRateChangePending = false;
    return updateVsyncConfig();
}

VsyncConfig VsyncModulator::updateVsyncConfig() {
    std::lock_guard<std::mutex> lock(mMutex);
    return updateVsyncConfigLocked();
}

VsyncConfig VsyncModulator::updateVsyncConfigLocked() {
    const VsyncConfig& offsets = getNextVsyncConfig();
    mVsyncConfig = offsets;

    if (mTraceDetailedInfo) {
        const bool isEarly = &offsets == &mVsyncConfigSet.early;
        const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
        const bool isLate = &offsets == &mVsyncConfigSet.late;

        ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
        ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
        ATRACE_INT("Vsync-LateOffsetsOn", isLate);
    }

    return offsets;
}

const VsyncConfig& VsyncModulator::getNextVsyncConfig() const {
    switch (getNextVsyncConfigType()) {
        case VsyncConfigType::Early:
            return mVsyncConfigSet.early;
        case VsyncConfigType::EarlyGpu:
            return mVsyncConfigSet.earlyGpu;
        case VsyncConfigType::Late:
            return mVsyncConfigSet.late;
    }
}

auto VsyncModulator::getNextVsyncConfigType() const -> VsyncConfigType {
    // Early offsets are used if we're in the middle of a refresh rate
    // change, or if we recently begin a transaction.
    if (!mEarlyWakeupRequests.empty() || mTransactionSchedule == Schedule::EarlyEnd ||
        mEarlyTransactionFrames > 0 || mRefreshRateChangePending) {
        return VsyncConfigType::Early;
    } else if (mEarlyGpuFrames > 0) {
        return VsyncConfigType::EarlyGpu;
    } else {
        return VsyncConfigType::Late;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

有三个不同的配置,early,earlyGPU,late,不同的情况下选择不同的配置


1

接着调用 setVsyncConfig

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
    setDuration(mAppConnectionHandle,
                /* workDuration */ config.appWorkDuration,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(mSfConnectionHandle,
                /* workDuration */ vsyncPeriod,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(config.sfWorkDuration);
}

void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
                            std::chrono::nanoseconds readyDuration) {
    android::EventThread* thread;
    {
        std::lock_guard<std::mutex> lock(mConnectionsLock);
        RETURN_IF_INVALID_HANDLE(handle);
        thread = mConnections[handle].thread.get();
    }
    thread->setDuration(workDuration, readyDuration);
}

void EventThread::setDuration(std::chrono::nanoseconds workDuration,
                              std::chrono::nanoseconds readyDuration) {
    std::lock_guard<std::mutex> lock(mMutex);
    mWorkDuration = workDuration;
    mReadyDuration = readyDuration;

    mVsyncRegistration.update({.workDuration = mWorkDuration.get().count(),
                               .readyDuration = mReadyDuration.count(),
                               .earliestVsync = mLastVsyncCallbackTime.ns()});
}

void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) {
    ATRACE_CALL();
    std::lock_guard lock(mVsync.mutex);
    mVsync.workDuration = workDuration;
    mVsync.scheduledFrameTime =
            mVsync.registration->update({.workDuration = mVsync.workDuration.get().count(),
                                         .readyDuration = 0,
                                         .earliestVsync = mVsync.lastCallbackTime.ns()});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
ScheduleResult VSyncCallbackRegistration::update(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    return mDispatch->update(*mToken, scheduleTiming);
}
1
2
3
4
5
6
ScheduleResult VSyncDispatchTimerQueue::update(CallbackToken token, ScheduleTiming scheduleTiming) {
    std::lock_guard lock(mMutex);
    const auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }

    auto& callback = it->second;
    // 
    if (!callback->targetVsync().has_value()) {
        return {};
    }

    return scheduleLocked(token, scheduleTiming);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
                                                       ScheduleTiming scheduleTiming) {
    auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }
    auto&       = it->second;
    auto const now = mTimeKeeper->now();

    /* If the timer thread will run soon, we'll apply this work update via the callback
     * timer recalculation to avoid cancelling a callback that is about to fire. */
    auto const rearmImminent = now > mIntendedWakeupTime;
    if (CC_UNLIKELY(rearmImminent)) {
        callback->addPendingWorkloadUpdate(scheduleTiming);
        return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
    }

    // 看下这个呢
    const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
    if (!result.has_value()) {
        return {};
    }

    if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
        rearmTimerSkippingUpdateFor(now, it);
    }

    return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    
    // 
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));

    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }

    nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
    nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return getExpectedCallbackTime(nextVsyncTime, timing);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

modulateVsync 实际就是给 EventThread 配置 workDuration readyDuration 参数。

# 5. Vsync-app 信号的申请与分发

# 5.1 SurfaceFlinger 端的初始化

我们先看 SurfaceFlinger 这边。

SurfaceFliner 对象初始化时,会调用到 SurfaceFlinger::initScheduler 函数,在该函数中会初始化两个 ConnectionHandle 对象。ConnectionHandle 对象通过本地 socket 向 App 端发送 Vsync 信号。

    std::unique_ptr<scheduler::Scheduler> mScheduler;
    scheduler::ConnectionHandle mAppConnectionHandle;
    scheduler::ConnectionHandle mSfConnectionHandle;

// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

// 参数就是前面构建的 DisplayDevice 对象
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    using namespace scheduler;

    // ......
    // VsyncConfigSet
    const auto configs = mVsyncConfiguration->getCurrentConfigs();

    // 关注点
    // 创建 VSYNC-app 对应的 EventThread
    mAppConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::Render,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ configs.late.appWorkDuration,
                                          /* readyDuration */ configs.late.sfWorkDuration);

    // 创建 VSYNC-appSf 对应的 EventThread
    mSfConnectionHandle =
            mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
                                          mFrameTimeline->getTokenManager(),
                                          /* workDuration */ activeRefreshRate.getPeriod(),
                                          /* readyDuration */ configs.late.sfWorkDuration);

    // ......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

这里通过 createEventThread 函数构建了两个 EventThread 对象。

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {
    
    // EventThread 初始化
    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           getVsyncSchedule(), tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;

    // ConnectionHandle 初始化
    handle = createEventThread(std::move(eventThread));
    return handle;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

接着看 EventThread 的构造函数:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.h

TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);

scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);

// 重要成员
State mState GUARDED_BY(mMutex) = State::Idle;


// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        // EventThread 的关键参数 mWorkDuration mReadyDuration
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        // 重要成员 mVsyncRegistration
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    // 构建一个线程对象
    // 执行 threadMain 函数
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

    pthread_setname_np(mThread.native_handle(), mThreadName);

    pid_t tid = pthread_gettid_np(mThread.native_handle());

    // Use SCHED_FIFO to minimize jitter
    constexpr int EVENT_THREAD_PRIORITY = 2;
    struct sched_param param = {0};
    param.sched_priority = EVENT_THREAD_PRIORITY;
    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO for EventThread");
    }

    set_sched_policy(tid, SP_FOREGROUND);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

EventThread 中记录了两个重要时间值

  • workduration:代表自身工作的理论耗时
  • readyduration:代表自身工作完成后,传递给下一模块处理的等待时间

app 的 workduration 代表 app 绘制渲染一帧的理论耗时,app 的 readyduration 代表 app 绘制渲染一帧完成后交给 surfaceflinger 处理的理论耗时。

接着看 EventThread 的另一个重要成员 scheduler::VSyncCallbackRegistration mVsyncRegistration 的初始化。


// 定义
class VSyncCallbackRegistration {
public:
    VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch>, VSyncDispatch::Callback,
                              std::string callbackName);
    ~VSyncCallbackRegistration();

    VSyncCallbackRegistration(VSyncCallbackRegistration&&);
    VSyncCallbackRegistration& operator=(VSyncCallbackRegistration&&);

    // See documentation for VSyncDispatch::schedule.
    ScheduleResult schedule(VSyncDispatch::ScheduleTiming scheduleTiming);

    // See documentation for VSyncDispatch::update.
    ScheduleResult update(VSyncDispatch::ScheduleTiming scheduleTiming);

    // See documentation for VSyncDispatch::cancel.
    CancelResult cancel();

private:
    friend class VSyncCallbackRegistrationTest;

    std::shared_ptr<VSyncDispatch> mDispatch;
    std::optional<VSyncDispatch::CallbackToken> mToken;
};


// 1. callback 的来源
VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
                                                     VSyncDispatch::Callback callback,
                                                     std::string callbackName)
      : mDispatch(std::move(dispatch)),
        // 2. registerCallback 流程 
        mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

callback 来自 createDispatchCallback 函数:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    // 直接返回一个 lamda
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}
1
2
3
4
5
6
7

直接返回一个 lamda,lamda 就是 EventThread::onVsync 的包装。

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
        Callback callback, std::string callbackName) {
    std::lock_guard lock(mMutex);
    return CallbackToken{
            mCallbacks
                    .emplace(++mCallbackToken,
                             std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
                                                                            std::move(callback),
                                                                            mMinVsyncDistance))
                    .first->first};
}
1
2
3
4
5
6
7
8
9
10
11
12

EventThread 初始化完成后,

ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {

    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           getVsyncSchedule(), tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    handle = createConnection(std::move(eventThread));
    return handle;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

接着调用 Scheduler::createConnection 创建 Connection 对象

createEventThread 函数返回的是 ConnectionHandle 结构体:

struct ConnectionHandle {
    using Id = std::uintptr_t;
    static constexpr Id INVALID_ID = static_cast<Id>(-1);

    Id id = INVALID_ID;

    explicit operator bool() const { return id != INVALID_ID; }
};
1
2
3
4
5
6
7
8

ConnectionHandle::Id mNextConnectionHandleId = 0;

std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock);

// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);

    // EventThreadConnection
    auto connection = createConnectionInternal(eventThread.get());

    std::lock_guard<std::mutex> lock(mConnectionsLock);
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

struct Connection {
    sp<EventThreadConnection> connection;
    std::unique_ptr<EventThread> thread;
};


sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) {

    int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
    // 关注点
    auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
    mLayerHistory.attachChoreographer(layerId, connection);
    return connection;
}

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
    return sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
                                           IPCThreadState::self()->getCallingUid(),
                                           std::move(resyncCallback), eventRegistration);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

其实就是 new 一个 EventThreadConnection 对象:

EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
                                             ResyncCallback resyncCallback,
                                             EventRegistrationFlags eventRegistration)
      : resyncCallback(std::move(resyncCallback)),
        mOwnerUid(callingUid),
        mEventRegistration(eventRegistration),
        mEventThread(eventThread),
        mChannel(gui::BitTube::DefaultSize) {}
1
2
3
4
5
6
7
8

mChannel 的类型是 BitTube ,包装了 socket ,用于与 app 通讯。

EventThreadConnection 中有几个重要的方法:

class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
	// 当vsync信号来临时,通过sockt-pair将信号发送给app
    virtual status_t postEvent(const DisplayEventReceiver::Event& event);
    // app通过binder跨进程调用此方法,将建立的socketpair返回给应用
    binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
    // binder跨进程方法跨进程调用此方法,将会向surfaceflinger请求一个vsync信号
    binder::Status requestNextVsync() override; // asynchronous

    VSyncRequest vsyncRequest = VSyncRequest::None;
    // .....
}
1
2
3
4
5
6
7
8
9
10
11
12

app 会向 surfaceflinger binder 建立连接,该连接就是 EventThreadConnection,是一个匿名 Binder。连接建立后会把该连接保存在 EventThread 的 mDisplayEventConnections 列表中。如上文代码所展示 EventThreadConnection 继承自 BnDisplayEventConnection,故 EventThreadConnection 具有使用 binder 跨进程的能力,且是 binder 的服务端类。建立连接后,app 端会调用 stealReceiveChannel 方法将 socketpair 返回给 app,后续的 vsync 信号将会使用该 socketpair 不断分发给 app。

# 5.2 App 端申请 Vsync-app 信号后,SurfaceFlinger 中的处理

关于 Choreographer 的内容很多,我们单独放一篇来说。

目前我们只需要知道,app 会向 surfaceflinger binder 建立连接,该连接就是 EventThreadConnection,是一个匿名 Binder。连接建立后会把该连接保存在 EventThread 的 mDisplayEventConnections 列表中。如上文代码所展示 EventThreadConnection 继承自 BnDisplayEventConnection,故 EventThreadConnection 具有使用 binder 跨进程的能力,且是 binder 的服务端类。建立连接后,app 端会调用 stealReceiveChannel 方法将 socketpair 返回给 app,后续的 vsync 信号将会使用该 socketpair 不断分发给 app。

binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    std::scoped_lock lock(mLock);
    if (mChannel.initCheck() != NO_ERROR) {
        return binder::Status::fromStatusT(NAME_NOT_FOUND);
    }

    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
    return binder::Status::ok();
}
1
2
3
4
5
6
7
8
9
10

很简单就是把 socketpair 的 fd 返回给 App 端。

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

binder::Status EventThreadConnection::requestNextVsync() {
    ATRACE_CALL();
    mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this));
    return binder::Status::ok();
}

void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

    std::lock_guard<std::mutex> lock(mMutex);

    // 第一次请求的时候 connection->vsyncRequest == VSyncRequest::None,进入如下逻辑,使得该连接的 vsyncRequest = VSyncRequest::Single
    // 第二次请求呢?
    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all();
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
        connection->vsyncRequest = VSyncRequest::Single;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

EventThreadConnection 的成员 VSyncRequest vsyncRequest 定义如下:

enum class VSyncRequest {
    None = -2,
    // Single wakes up for the next two frames to avoid scheduler overhead
    Single = -1,
    // SingleSuppressCallback only wakes up for the next frame
    SingleSuppressCallback = 0,
    Periodic = 1,
    // Subsequent values are periods.
};
1
2
3
4
5
6
7
8
9

vsyncRequest 保存着对应 EventThreadConnection 申请 vsync 的状态

  • None:不请求
  • Single :该状态下会得到两次软件 vsync 回调
  • SingleSuppressCallback :该状态下会得到一次vsync回调
  • Periodic:亮屏下不使用该状态

requestNextVsync 相关变量的情况如下:

  • mPendingEvents.isEmpty() = true
  • mState = State::IDLE
  • connection->vsyncRequest = VSyncRequest::Single

这里修改 VSyncRequest 的值并唤醒 mCondition 上等待的线程。

EventThread 线程会在 connection 上 wait:

std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
std::vector<wp<EventThreadConnection>> mDisplayEventConnections;
std::optional<VSyncState> mVSyncState GUARDED_BY(mMutex);

void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {

    DisplayEventConsumers consumers;

    while (mState != State::Quit) {

        std::optional<DisplayEventReceiver::Event> event;

        // 取 event
        // mPendingEvents,存放着定时器唤醒后发给该EventThread的事件,
        // Determine next event to dispatch.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
                if (event->hotplug.connected && !mVSyncState) {
                    mVSyncState.emplace(event->header.displayId);
                } else if (!event->hotplug.connected && mVSyncState &&
                           mVSyncState->displayId == event->header.displayId) {
                    mVSyncState.reset();
                }
            }
        }

        bool vsyncRequested = false;

        // 遍历所有连接
        // 找到 consumer
        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                if (event && shouldConsumeEvent(*event, connection)) { // 关注点
                    consumers.push_back(connection);
                }
                // 变为 true
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        // 分发 event 给 consumer
        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }

        if (mVSyncState && vsyncRequested) {
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            mState = State::Idle;
        }

        if (mState == State::VSync) {
            // 请求 VSync 信号
            // 实际就是向 mPendingEvents 添加 event
            const auto scheduleResult =
                    mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                                 .readyDuration = mReadyDuration.count(),
                                                 .earliestVsync = mLastVsyncCallbackTime.ns()});
                                                 
            LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
        } else {
            mVsyncRegistration.cancel();
        }

        if (!mPendingEvents.empty()) {
            continue;
        }
        
        // 等待 app 唤醒
        // Wait for event or client registration/request.
        if (mState == State::Idle) {
            mCondition.wait(lock);
        } else {
            // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
            // display is off, keep feeding clients at 60 Hz.
            const std::chrono::nanoseconds timeout =
                    mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                if (mState == State::VSync) {
                    ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                }

                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp));
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

从 wait 唤醒后,会调用 mVsyncRegistration.schedule 请求软件 VSync 信号。

// frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
 
ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    return mDispatch->schedule(*mToken, scheduleTiming);
}
1
2
3
4
5
6
7
8
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
 
ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) {
    std::lock_guard lock(mMutex);
    return scheduleLocked(token, scheduleTiming);
}

ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
                                                       ScheduleTiming scheduleTiming) {
    auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }
    auto& callback = it->second;
    auto const now = mTimeKeeper->now();
 
    /* If the timer thread will run soon, we'll apply this work update via the callback
     * timer recalculation to avoid cancelling a callback that is about to fire. */
    auto const rearmImminent = now > mIntendedWakeupTime;
    if (CC_UNLIKELY(rearmImminent)) {
        callback->addPendingWorkloadUpdate(scheduleTiming);
        return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
    }
     
    // 关注点
    const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
    if (!result.has_value()) {
        return {};
    }
    
    // 关注点
    if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
        rearmTimerSkippingUpdateFor(now, it);
    }
 
    return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

拿到回调对象 callback 然后调用 schedule。

callback 的类型是 VSyncDispatchTimerQueueEntry,接着调用 callback 的 schedule 函数:

// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQue ue.cpp
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    // 计算出 now + timing.workDuration + timing.readyDuration 时间点开始的下一次硬件 Vsync 信号
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    
    // 计算出的软件 Vsync 时间点
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
 
    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }
 
    nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
    nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
 
    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    // 计算结果存到成员  mArmedInfo 中
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return getExpectedCallbackTime(nextVsyncTime, timing);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const {
    std::lock_guard lock(mMutex);

    // update the mLastVsyncSequence for reference point
    mLastVsyncSequence = getVsyncSequenceLocked(timePoint);

    const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
        if (!mRenderRate) return 0;

        const auto divisor =
                RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod),
                                                         *mRenderRate);
        if (divisor <= 1) return 0;

        const int mod = mLastVsyncSequence->seq % divisor;
        if (mod == 0) return 0;

        return divisor - mod;
    }();

    if (renderRatePhase == 0) {
        return mLastVsyncSequence->vsyncTime;
    }

    auto const [slope, intercept] = getVSyncPredictionModelLocked();
    const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
    return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

这里就是计算下一次 VSync 的地方了。tracker 就是 VSyncPredictor,是计算 VSync 的核心类。

workduration 和 readyduration 在大多数情况下都是固定值,且对于 sync 计算来说是个固定值,是对于 app 和 sf 完成渲染和合成工作时间大概估计,vsync 时间点的计算和这两个值有关系。

如下图所示,是app-sync的时间点计算示意图: 举例: app-sync: workduration:16.6ms readyduration: 15.6ms,那么 app-sync 的计算方式如下图所描述:

20240730222025

图片来自:https://blog.csdn.net/qq_41095045/article/details/136378829?spm=1001.2014.3001.5502

  • 假如应用在24.9ms时向surfaceflinger申请app-vsync信号
  • 在24.9ms基础上加上app-vsync的workduration和readyduration计算出时间点a
  • 找出a的下一个HW_VSYNC的时间点:81ms
  • 在a的的下一个HW_VSYNC的时间点上减去app-vsync的workduration和readyduration得到时间点b:48.8ms,改时间点就是未来app收到app-vsync的时间点
  • 计算出surfaceflinger申请app-vsync信号的到时间点b的时间差:23.9ms,并设置定时
  • 23.9m后app申请的app-vsync时间到,surfaceflinger向app发送app-vsync信号

以上演示的以 app-vsync 为例的 vsync 计算过程,appsf-vsync 和sf-vsync 的计算过程类似,不同的是appsf-vsync和sf-vsync的workduration,readyduration是不同的值,以使得信号之间保持一定的相位差。

在上面的 VSyncDispatchTimerQueue::scheduleLocked 中,schedule 计算完时间后,会调用 rearmTimerSkippingUpdateFor,而 rearmTimerSkippingUpdateFor 设置了一个 Alarm,定时执行 VSync 的回调:

void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
        nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
        //...
        setTimer(*min, now);
        //...
}
 
void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    mIntendedWakeupTime = targetTime;
    // 定时回调 VSyncDispatchTimerQueue::timerCallback
    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
                         mIntendedWakeupTime);
    mLastTimerSchedule = mTimeKeeper->now();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

时间到了就会唤醒:

void VSyncDispatchTimerQueue::timerCallback() {
    struct Invocation {
        std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
        nsecs_t vsyncTimestamp;
        nsecs_t wakeupTimestamp;
        nsecs_t deadlineTimestamp;
    };
    std::vector<Invocation> invocations;
    {
        std::lock_guard lock(mMutex);
        auto const now = mTimeKeeper->now();
        mLastTimerCallback = now;
        // 遍历所有的 VSyncDispatchTimerQueueEntry
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) { 
            // 遍历取出 callback
            auto& callback = it->second;
            auto const wakeupTime = callback->wakeupTime();
            if (!wakeupTime) {
                continue;
            }

            auto const readyTime = callback->readyTime();

            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                // callback 包装到 Invocation 中
                invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
                                                    *wakeupTime, *readyTime});
            }
        }

        mIntendedWakeupTime = kInvalidTime;
        rearmTimer(mTimeKeeper->now());
    }

    for (auto const& invocation : invocations) {
        // 回调
        invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
                                      invocation.deadlineTimestamp);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

对于 EventThread ,这里的 callback 来自 createDispatchCallback 函数:

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}
1
2
3
4
5
std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);

void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
 
    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    // 构建一个 event 添加到 mPendingEvents 中
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                    vsyncTime, readyTime));

    // 唤醒 EventThread
    mCondition.notify_all();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
                                      uint32_t count, nsecs_t expectedPresentationTime,
                                      nsecs_t deadlineTimestamp) {
    DisplayEventReceiver::Event event;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
    event.vsync.count = count;
    event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
    // Temporarily store the current vsync information in frameTimelines[0], marked as
    // platform-preferred. When the event is dispatched later, the frame interval at that time is
    // used with this information to generate multiple frame timeline choices.
    event.vsync.vsyncData.frameTimelines[0] = {.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
                                               .deadlineTimestamp = deadlineTimestamp,
                                               .expectedPresentationTime =
                                                       expectedPresentationTime};
    return event;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Vsync 信号将会封装成 Event 放入 mPendingEvents,然后调用锁对象 mCondition 的 notify_all 通知其他 wait 在这个锁对象的线程。

EventThread 中的 threadmain 方法从 wait 中唤醒:

在之前的 threadMain 方法中,有代码:

if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
 
            if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
                if (event->hotplug.connected && !mVSyncState) {
                    mVSyncState.emplace(event->header.displayId);
                } else if (!event->hotplug.connected && mVSyncState &&
                           mVSyncState->displayId == event->header.displayId) {
                    mVSyncState.reset();
                }
            }
        }
//...
if (!consumers.empty()) {
    dispatchEvent(*event, consumers);
    consumers.clear();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

dispatchEvent 分发:

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            copy.vsync.vsyncData.frameInterval = frameInterval;
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        // 关注点,分发事件
        switch (consumer->postEvent(copy)) { 
            case NO_ERROR:
                break;
 
            case -EAGAIN:
                // TODO: Try again if pipe is full.
                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
                      toString(*consumer).c_str());
                break;
 
            default:
                // Treat EPIPE and other errors as fatal.
                removeDisplayEventConnectionLocked(consumer);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

这里的 consumer 为 EventThreadConnection:

// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
 
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    constexpr auto toStatus = [](ssize_t size) {
        return size < 0 ? status_t(size) : status_t(NO_ERROR);
    };
 
    if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
        event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
        mPendingEvents.emplace_back(event);
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
            return status_t(NO_ERROR);
        }
 
        auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
                                                     mPendingEvents.size());
        mPendingEvents.clear();
        return toStatus(size);
    }
 
    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

DisplayEventReceiver::sendEvents 最终发给客户端:

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}
1
2
3
4
5

BitTube 通过 socket 将事件分发到客户端的 Choreographer。

# 5.3 Vsync-sf 信号的申请与分发

当 sf 需要请求刷新时,会调用到 MessageQueue::scheduleFrame 函数。

void MessageQueue::scheduleFrame() {
    ATRACE_CALL();

    std::lock_guard lock(mVsync.mutex);
    mVsync.scheduledFrameTime =
            mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                           .readyDuration = 0,
                                           .earliestVsync = mVsync.lastCallbackTime.ns()});
}
1
2
3
4
5
6
7
8
9

计算过程都是和 app 一样的,最终的回调函数不一样,这里是 MessageQueue::vsyncCallback

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
 
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;
 
    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }
 
    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};
 
    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

MessageQueue本身是一个消息队列的实现类。这里看到收到 VSync 回调后,通过 mHandler->dispatchFrame 抛到队列里去了。最终会执行

// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
 
void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}
1
2
3
4
5
6
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
 
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
          // ...
          if (!compositor.commit(pacesetterId, targets)) return;
          // ...
          const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
  }
1
2
3
4
5
6
7
8
9

这里的 compositor 是 SurfaceFlinger。接下来就是由 SF 进行合成工作了即执行 commit 和 composite 两个函数。

# 软件 Vsync 信号计算模型的建立与校准

为了避免频繁的打开硬件 VSYNC 来产生 VSYNC 信号,故在 SurfaceFlinger 中除了还维持了一个软件 VSYNC 信号模型,当 app 申请 app-vsync 信号时,不会直接采用硬件 VSYNC,而是通过软件 VSYNC 信号模型,只需要向模型输入需要 VSYNC 的时间,模型变计算出合适的软件 VSYNC 时间,随后等到计算出的软件 VSYNC 时间到了,向应用下发一个 app-vsync 信号。但是,用模拟出来的 VSYNC 信号模型随着使用难免产生误差,当误差过大时便打开硬件 VSYNC 对 VSYNC 信号模型进行校准。